package org.phalanx.client.mapeditor.dialogs;

import java.awt.Color;
import java.awt.Container;
import java.awt.FlowLayout;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;

import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.TitledBorder;

import org.phalanx.client.PhalanxClient;
import org.phalanx.client.UI.DialogManager;
import org.phalanx.client.UI.PhalanxIconButton;
import org.phalanx.client.UI.swing.PhalanxButtonFactory;
import org.phalanx.client.UI.swing.listeners.pButtonListener;
import org.phalanx.client.UI.swing.listeners.pButtonPressed;
import org.phalanx.client.mapeditor.PhalanxMapEditorPanel;
import org.phalanx.client.mapeditor.PhalanxMapTileSetChooserPanel;
import org.phalanx.client.properties.ClientPreferences;
import org.phalanx.digest.MessageDigestManager;
import org.phalanx.map.MapTileSet;
import org.phalanx.map.PhalanxMap;
import org.phalanx.map.PhalanxTileSetReader;
import org.phalanx.zip.ZipFileArchiveReader;

public class PhalanxMapTileSetChooserDialog extends JFrame implements pButtonListener {
	private static final long serialVersionUID = 8050734376782165785L;
	public static final String NAME = "TILESETCHANGER";
	private PhalanxMapTileSetChooserPanel chooserPanel;
	private PhalanxMapEditorPanel masterPanel;
	private JPanel contextPanel;
	private PhalanxIconButton okButton;
	private PhalanxIconButton cancelButton;
	
	public PhalanxMapTileSetChooserDialog(PhalanxMapEditorPanel parentPanel) {
		masterPanel = parentPanel;
		initializeFrame();
		setUpLocalComponents();
		setUpPanels();
		
		this.setContentPane(contextPanel);
	}
	
	private void initializeFrame() {
		this.setBackground(Color.black);
		this.setSize(400,400);
		this.setTitle("Change Tileset");
		
		JFrame masterFrame = masterPanel.getMasterFrame();
		int pX = ((masterFrame.getWidth() + masterFrame.getLocation().x) + 
				masterFrame.getLocation().x) / 5;
		int pY = ((masterFrame.getHeight() + masterFrame.getLocation().y) + 
				masterFrame.getLocation().y) / 5;
		
		this.setLocation(pX, pY);
	}
	
	private void setUpLocalComponents() {
		okButton = PhalanxButtonFactory.getButton(PhalanxButtonFactory.DEFAULT_OK_BUTTON);
		cancelButton = PhalanxButtonFactory.getButton(PhalanxButtonFactory.DEFAULT_CANCEL_BUTTON);
		
		okButton.addButtonListener(this);
		cancelButton.addButtonListener(this);
	}
	
	private void setUpPanels() {
		contextPanel = new JPanel();
		contextPanel.setBackground(Color.black);
		contextPanel.setLayout(new GridBagLayout());
		
		chooserPanel = new PhalanxMapTileSetChooserPanel();
		
		TitledBorder t = BorderFactory.createTitledBorder("Tile Set Chooser");
		t.setTitleColor(Color.white);
		
		chooserPanel.setBorder(t);
		
		GridBagConstraints c = new GridBagConstraints();
		c.gridx = 0;
		c.gridy = 0;
		c.fill = GridBagConstraints.BOTH;
		c.weightx = 0.5;
		c.weighty = 0.5;
		
		contextPanel.add(chooserPanel, c);
		
		c = new GridBagConstraints();
		c.gridx = 0;
		c.gridy = 1;
		c.fill = GridBagConstraints.HORIZONTAL;
		
		Container buttonPanel = new Container();
		buttonPanel.setBackground(Color.black);
		buttonPanel.setLayout(new FlowLayout(FlowLayout.RIGHT));
		buttonPanel.add(okButton);
		buttonPanel.add(cancelButton);
		
		contextPanel.add(buttonPanel, c);
	}
	
	public void closeWindow() {
		DialogManager d = DialogManager.getInstance();
		d.removeDialog(NAME);
		this.dispose();
	}

	public void actionPerformed(pButtonPressed p) {
		if (p.getComponent().equals(okButton)) {
			applyTileSetToMap();
			this.closeWindow();
		}
		else if (p.getComponent().equals(cancelButton)) {
			this.closeWindow();
		}
		
	}
	
	private boolean applyTileSetToMap() {
		boolean isSuccess = false;
		//PhalanxMap currentMap = masterPanel.getDisplayContainer().getMapViewObject().getMap();
		MapTileSet newSet = loadTileSet();
		
		if (newSet != null) {
			//currentMap.setMapTileSet(newSet);
			masterPanel.getDisplayContainer().getMapViewObject().setMapTileSet(newSet);
			masterPanel.rehashTileSetViewer();
			masterPanel.getDisplayContainer().getMapViewObject().repaint();
			isSuccess = true;
		}
		
		return isSuccess;
	}
	
	private MapTileSet loadTileSet() {
		String tileFilePath = chooserPanel.getFilePath().getText();
		MapTileSet newSet = null;
		
		if (chooserPanel.getIsDefaultSelected()) {
			newSet = new MapTileSet();
			newSet = PhalanxClient.getClientInstance().getDefaultTileSet();
			
		}
		else {
			if (validatePath(tileFilePath)) {
				try {
					PhalanxTileSetReader r = new PhalanxTileSetReader();
					r.setTerrainFileByName(tileFilePath);
					r.readInTerrain();
					newSet = r.getMapTileSet();
					newSet.setTileSetArchiveFile(tileFilePath);
					String canonicalFileName = moveToCacheAndGetCacheName(tileFilePath);
					newSet.setCanonicalFilePath(canonicalFileName);
					
					if (newSet.getMapTileSetTable().isEmpty()) {
						newSet = null;
					}
				} catch (IOException ie) {}
			}
			
		}
		
		return newSet;
	}
	
	private String moveToCacheAndGetCacheName(String fileName) {
		String cachedName = "";
		
		try {
			File tileSetFile = new File(fileName);

			DataInputStream dIn = new DataInputStream(new FileInputStream(tileSetFile));

			byte[] b = new byte[(int)tileSetFile.length()];
			
			int startPos = 0;
			
			while(startPos != -1){
				startPos = dIn.read(b, startPos, b.length - startPos);
			}

			String md5String = MessageDigestManager.getMD5Hash(b);
			createCachedTileSet(md5String, b);
			cachedName = md5String + ".zip";

		} catch (IOException e) {}

		return cachedName;
	}
	
	private boolean createCachedTileSet(String namePrefix, byte[] fileBytes){
		ClientPreferences p = PhalanxClient.getClientInstance().getPreferences();
		File cachedFile = new File(p.getProperties("PhalanxClient.PhalanxGame.Mapping.CacheDirectory") + "/" + namePrefix + ".zip");
		boolean isSuccess = false;
		
		try {
		if (!cachedFile.exists()){
			FileOutputStream fOut = new FileOutputStream(cachedFile);
			fOut.write(fileBytes);
			isSuccess = true;
		}
		} catch (IOException ie){}
		
		return isSuccess;
	}
	
	private boolean validatePath(String path) {
		boolean isSuccess = false;
		
		File validFile = new File(path);
		
		if (validFile.exists()) {
			isSuccess = true;
		}
		return isSuccess;
	}
}
